(() => {
  if (window.Callback && window.Client) {
    return;
  }

  let Callback = (window.Callback = {
    count: 0,
    data: {},
    eventHandler: {},
    add: (func, keep) => {
      if (typeof func !== "function") {
        return func;
      }

      if (typeof keep === "undefined") {
        keep = 0;
      }

      Callback.count++;
      Callback.data[Callback.count] = { func: func, keep: keep };
      return "Callback.run(" + Callback.count + ")";
    },
    run: id => {
      if (
        typeof Callback.data === "undefined" ||
        typeof Callback.data[id] === "undefined"
      ) {
        return false;
      }

      let callbackFunc = Callback.data[id].func;
      if (Callback.data[id].keep !== 1) {
        delete Callback.data[id];
      }
      return callbackFunc;
    },
    registerEvent(eventName, callback) {
      if (!eventName) {
        return;
      }
      let handlers = Callback.eventHandler[eventName];
      if (!handlers) {
        Callback.eventHandler[eventName] = handlers = [];
      }
      const handler = handlers.push(callback);
      return `${eventName}__${handler}`;
    },
    unregisterEvent(eventName, handler) {
      const handlers = Callback.eventHandler[eventName];
      if (handlers) {
        const strArray = handler.split("__");
        if (strArray.length > 1 && +strArray[1] > -1) {
          handlers.splice(handler - 1, 1);
        }
      }
    },
    fireEvent(eventName, data) {
      const handlers = Callback.eventHandler[eventName];
      if (handlers && handlers.length) {
        for (const handler of handlers) {
          if (handler) {
            handler(data);
          }
        }
      }
    }
  });

  const prefix = "editor";

  function invoke(methodName, arg) {
    console.log("invoke called", typeof window.WebViewJavascriptBridge);
    let namespace = prefix + "." + methodName;
    if (
      typeof window.WebViewJavascriptBridge !== "undefined" &&
      typeof window.WebViewJavascriptBridge.invoke !== "undefined"
    ) {
      console.log("invoke", methodName, arg);
      return window.WebViewJavascriptBridge.invoke(namespace, arg);
    } else if (
      typeof window.webkit != "undefined" &&
      typeof window.webkit.messageHandlers[methodName] != "undefined"
    ) {
      console.log("invoke2", methodName, arg);
      return window.webkit.messageHandlers[methodName].postMessage(arg);
    } else {
      console.log("invoke3", methodName, arg);
      // 解决Android时机问题
      addEventListener(
        "WebViewJavascriptBridgeReady",
        () => {
          console.log(2222);
          invoke(methodName, arg);
        },
        false
      );
    }
  }

  window.Client = {
    /**
     * 获取用户信息
     */
    getUserInfo: (success, error) => {
      return invoke("getUserInfo", {
        success: Callback.add(success),
        error: Callback.add(error)
      });
    },
    /**
     * 打开相册
     */
    openAlbum: () => {
      return invoke("openAlbum");
    },
    // openAlbum: () => {
    //   return invoke("openAlbum");
    // },
    /**
     * Native event call back
     * @param {*} eventName
     * @param {*} data
     */
    onNativeEvent: (eventName, data) => {
      console.log(`Native call web event: ${eventName}, data: `, data);
      Callback.fireEvent(eventName, data);
    },
    /**
     * 写日志到native
     * @param {*} msg
     */
    writeLog: msg => {
      console.log("call writeLog, msg = ", msg);
      return invoke("writeLog", {
        msg: msg
      });
    },
    /**
     * 获取api
     * @param {*} jsApiList api列表
     * @param {*} success
     */
    checkJsApi: (jsApiList, success) => {
      return invoke("checkJsApi", {
        jsApiList: jsApiList,
        success: Callback.add(success)
      });
    },
    /**
     * 获取客户端版本信息
     * @param {*} jsApiList api列表
     * @param {*} success
     */
    getJsApiVersion: success => {
      return invoke("getJsApiVersion", {
        success: Callback.add(success)
      });
    },

    /**
     * 设置页面标题
     * @param {*} title 页面标题
     */
    setTitle: (title, subTitle) => {
      return invoke("setTitle", { title: title, subTitle });
    },

    /**
     * 返回
     */
    goBack: () => {
      return invoke("goBack");
    },

    /**
     * 获取登录信息
     * @param {*} success
     */
    getTokenInfo: success => {
      return invoke("getTokenInfo", { success: Callback.add(success) });
    },

    /**
     * 购买表情 or 心情
     * @param {*} type 1 心情  2表情
     * @param {*} objectId 对象id
     * @param {*} success
     * @param {*} error
     */
    buy: (type, objectId, success, error) => {
      return invoke("buy", {
        type: type,
        objectId: objectId,
        success: Callback.add(success),
        error: Callback.add(error)
      });
    },

    /**
     * 下载表情 or 心情
     * @param {*} type 1 心情  2表情
     * @param {*} objectId 对象id
     * @param {*} downloadUrl 下载url
     * @param {*} coverUrl 主图链接
     * @param {*} iconName 图片名字
     * @param {*} title
     * @param {*} success
     * @param {*} error
     * @param {*} event 进度条事件
     * @param version
     */
    download: function(
      type,
      objectId,
      downloadUrl,
      coverUrl,
      iconName,
      title,
      success,
      error,
      event,
      version
    ) {
      return invoke("download", {
        type: type,
        objectId: objectId,
        version: version,
        downloadUrl: downloadUrl,
        coverUrl: coverUrl,
        iconName: iconName,
        title: title,
        success: Callback.add(success, 1),
        error: Callback.add(error, 1),
        event: Callback.add(event, 1)
      });
    },

    /**
     * 设置header 右侧按钮
     * @param {*} type  1文字 2 图片
     * @param {*} content  文字 / icon图片地址
     * @param {*} success 成功回调
     */
    setRightButton: (type, content, success) => {
      return invoke("setRightButton", {
        type: type,
        content: content,
        success: Callback.add(success, 1)
      });
    },

    /**
     * 获取下载状态
     * @param {*} type 表情、心情区别 1 心情  2表情
     * @param {*} objectId 对象id
     * @param {*} success 成功回调
     * downloadStatus => 1 已下载 0未下载
     */
    getDownloadStatus: (type, objectId, success) => {
      console.log("type===>", type);
      return invoke("getDownloadStatus", {
        type: type,
        objectId: objectId,
        success: Callback.add(success)
      });
    },

    /**
     * 下载
     * @param {*} type 表情、心情区别 1 心情  2表情
     * @param {*} objectId 对象id
     * @param {*} success 成功回调
     * @param {*} error 失败回调
     */
    useDownloaded: (type, objectId, success, error) => {
      return invoke("useDownloaded", {
        type: type,
        objectId: objectId,
        success: Callback.add(success, 1),
        error: Callback.add(error, 1)
      });
    },

    /**
     * 关闭当前webView
     */
    closeWindow: () => {
      return invoke("closeWindow");
    },

    /**
     * 将右侧按钮去掉
     */
    clearRightButton() {
      this.setRightButton(1, "", () => {});
    },

    /**
     * 上传图片视频
     * @param {*} maxSelectNum 可上传最大值
     * @param {*} success 成功回调
     * @param {*} error 失败回调
     * @param {*} event 单个成功回调
     */
    uploadFiles: (maxSelectNum, success, error, event) => {
      return invoke("uploadFiles", {
        maxSelectNum: maxSelectNum,
        success: Callback.add(success),
        error: Callback.add(error),
        event: Callback.add(event, 1)
      });
    },

    /**
     * 录制语音
     * @param {*} minDuration 录制最小时长
     * @param {*} maxDuration 录制最大时长
     * @param {*} success 成功回调
     * @param {*} error 失败回调
     */
    recordingVoice: (minDuration, maxDuration, success, error) => {
      return invoke("recordingVoice", {
        minDuration: minDuration,
        maxDuration: maxDuration,
        success: Callback.add(success),
        error: Callback.add(error)
      });
    },

    /**
     * 表情心情是否隐藏
     * @param {*} type 表情、心情区别 1 心情  2表情
     * @param {*} objectId 该对象id
     * @param {*} isHidden 设置是否隐藏 1 隐藏 0 显示
     * @param {*} success 成功回调
     * @param {*} error 失败回调
     */
    setIsHidden: (type, objectId, isHidden, success, error) => {
      return invoke("setIsHidden", {
        type: type,
        objectId: objectId,
        isHidden: isHidden,
        success: Callback.add(success, 1),
        error: Callback.add(error, 1)
      });
    },

    /**
     * 表情兑换完成
     */
    exchangeSuccess: () => {
      return invoke("exchangeSuccess");
    },

    /**
     * 云账户回调
     */
    YZHJScloseView: () => {
      return invoke("YZHJScloseView");
    },

    /**
     * 打开页面 参见http://172.18.94.196:8090/display/CLIENTWIKI/JS+Bridge
     * @param {*} pageName  页面名称
     * @param {*} params 参数
     * @param keepBrowserWindow 是否包括当前WebView窗口
     */
    open: (pageName, params, success, keepBrowserWindow) => {
      return invoke("open", {
        pageName: pageName,
        params: params,
        keepBrowserWindow: keepBrowserWindow,
        success: Callback.add(success, 1)
      });
    },

    /**
     * 分享等级
     * @param {*} imageUrl 参数
     */
    shareUpgrade: imageUrl => {
      return invoke("shareUpgrade", {
        imageUrl: imageUrl
      });
    },
    /**
     * 分享
     * @param {*} type  类型 1 微信好友 2 微信朋友圈 3 QQ
     * @param {*} title 标题
     * @param {*} desc 描述
     * @param {*} link 跳转地址
     * @param {*} imgUrl 图片地址
     * @param {*} success 参数
     */
    share: (type, title, desc, link, imgUrl, success, error) => {
      return invoke("share", {
        type: type,
        title: title,
        desc: desc,
        link: link,
        imgUrl: imgUrl,
        success: Callback.add(success),
        error: Callback.add(error)
      });
    },

    /**
     * 获取定位信息
     * @param {*} success 成功回调 res = > {latitude:'', longitude:'', country:'', province:'', 'city':''}
     * @param {*} error 失败回调 res => {'msg':''}
     */
    getLocationInfo: (success, error) => {
      return invoke("getLocationInfo", {
        success: Callback.add(success),
        error: Callback.add(error)
      });
    },

    /**
     * 刷新页面
     * @param {*} pageName  页面名称
     * @param {*} params 参数
     */
    refresh: (pageName, params) => {
      return invoke("refresh", {
        pageName: pageName,
        params: params
      });
    },

    /**
     *获取个人信息
     */
    getMyProfile: success => {
      return invoke("getMyProfile", { success: Callback.add(success) });
    },

    /**
     * 购买会员
     * @param {*} count 购买数量
     * @param {*} id 标题
     * @param {*} amount 金额
     * @param {*} payType 支付方式
     * @param {*} productId 产品id
     * @param {*} success 购买成功回调
     */
    buyVip: (count, id, amount, payType, productId, success, error) => {
      return invoke("buyVip", {
        count: count,
        id: id,
        amount: amount,
        payType: payType,
        productId: productId,
        success: Callback.add(success),
        error: Callback.add(error)
      });
    },

    /**
     * 设置成长明细已读
     */
    detailRead: () => {
      return invoke("detailRead");
    },

    /**
     * 发布小记
     * @param {*} html 富文本
     * @param {*} levels 浮动层
     * @param {*} paint 涂鸦
     * @param {*} bg 背景
     * @param {*} isCache 是否缓存，点下一步为false 定时缓存为true
     * @param {*} success
     * @param {*} error
     */
    smallnoteSubmit: (
      html,
      text,
      levels,
      paint,
      bg,
      size,
      isCache,
      success,
      error
    ) => {
      return invoke("smallnoteSubmit", {
        html,
        text,
        levels,
        paint,
        bg,
        size,
        isCache,
        success: Callback.add(success),
        error: Callback.add(error)
      });
    },

    /**
     * 获取客户端小记缓存
     * @param {*} success
     */
    getSmallnoteCache: success => {
      return invoke("getSmallnoteCache", { success: Callback.add(success) });
    },

    /**
     * 获取客户端小记详情
     * @param {*} success
     */
    getSmallnoteDetail: success => {
      return invoke("getSmallnoteDetail", { success: Callback.add(success) });
    },

    /**
     * 上传图片视频
     * @param {*} maxSelectNum 可上传最大值
     * @param {*} onlyImage 是否过滤视频
     * @param {*} success 成功回调
     * @param {*} error 失败回调
     * @param {*} event 单个成功回调
     */
    smallNoteGetFiles: (maxSelectNum, onlyImage, success, error, event) => {
      return invoke("smallNoteGetFiles", {
        maxSelectNum: maxSelectNum,
        onlyImage,
        success: Callback.add(success),
        error: Callback.add(error),
        event: Callback.add(event, 1)
      });
    },

    /**
     * 发布笔记（编辑/移动笔记）
     * @param {*} notebookId 笔记本ID
     * @param {*} noteId 笔记ID（为0则是创建）
     * @param {*} notebookMoveId 移动的笔记本ID（为0则是创建或者修改）
     * @param {*} title 标题
     * @param {*} thumb 缩略图
     * @param {*} intro 简介
     * @param {*} content 内容 包括{html,paint,levels}
     * @param {*} paper 背景
     * @param {*} type 保存类型 1 添加 2 修改 3 移动 4 本地缓存
     * @param {*} success
     * @param {*} error
     */
    notebookArticleSubmit: (
      notebookId,
      noteId,
      notebookMoveId,
      title,
      thumb,
      intro,
      content,
      paper,
      size,
      type,
      success,
      error
    ) => {
      return invoke("notebookArticleSubmit", {
        notebookId,
        noteId,
        notebookMoveId,
        title,
        thumb,
        intro,
        content,
        paper,
        size,
        type,
        success: Callback.add(success),
        error: Callback.add(error)
      });
    },

    /**
     * 删除笔记
     * @param {*} notebookId 笔记本ID
     * @param {*} noteId 笔记ID
     * @param {*} success
     * @param {*} error
     */
    notebookArticleDelete: (notebookId, noteId, success, error) => {
      return invoke("notebookArticleDelete", {
        notebookId,
        noteId,
        success: Callback.add(success),
        error: Callback.add(error)
      });
    },

    /**
     * 获取客户端笔记缓存
     * @param {*} notebookId 笔记本ID
     * @param {*} noteId 笔记ID
     * @param {*} success
     */
    getNotebookArticleCache: (notebookId, noteId, success) => {
      return invoke("getNotebookArticleCache", {
        notebookId,
        noteId,
        success: Callback.add(success)
      });
    },

    /**
     * 获取设置的留海高度
     * @param {*} success
     */
    getSafeArea: success => {
      return invoke("getSafeArea", { success: Callback.add(success) });
    },

    /**
     * 录音初始化
     * @param {*} success 成功回调
     * @param {*} error 失败回调
     */
    recordInit: (success, error) => {
      return invoke("recordInit", {
        success: Callback.add(success),
        error: Callback.add(error)
      });
    },

    /**
     * 录音开始
     * @param {*} success 成功回调
     * @param {*} error 失败回调
     */
    recordStart: (success, error) => {
      return invoke("recordStart", {
        success: Callback.add(success),
        error: Callback.add(error)
      });
    },

    /**
     * 录音结束
     * @param {*} success 成功回调
     * @param {*} error 失败回调
     */
    recordEnd: (success, error) => {
      return invoke("recordEnd", {
        success: Callback.add(success),
        error: Callback.add(error)
      });
    },

    /**
     * 文件删除
     * @param {*} url 文件url
     * @param {*} success 成功回调
     * @param {*} error 失败回调
     */
    fileDelete: (url, success, error) => {
      return invoke("fileDelete", {
        url,
        success: Callback.add(success),
        error: Callback.add(error)
      });
    },

    /**
     * 弹出键盘
     */
    becomeEditing: () => {
      return invoke("becomeEditing");
    },

    /**
     * 收起键盘
     * @param {*} success
     */
    endEditing: () => {
      return invoke("endEditing");
    },

    /**
     * 获取web项目版本号
     * @param {*} project web项目
     */
    getWebVersion: (project = "RichEditorUpdateTimestampKey", success) => {
      return invoke("getWebVersion", {
        project,
        success: Callback.add(success)
      });
    },

    /**
     * 禁止webview滚动
     * @param {*} scrollEnabled 是否滚动
     */
    isScroll: scrollEnabled => {
      return invoke("isScroll", { scrollEnabled });
    },

    /**
     * 是否开启滑动关闭手势
     * @param {*} enabled 是否允许手势
     */
    panGestureEnable: enabled => {
      return invoke("panGestureEnable", { enabled });
    },

    /**
     * 选择联系人
     * @param {*} enableMultiSelect 是否支持多选
     * @param {*} selectedUids 已选人员ids
     * @param {*} maxCount 最大数量限制
     * @param {*} success 成功回调
     * @param {*} error 失败回调
     */
    selectContacts: function(
      enableMultiSelect,
      selectedUids,
      maxCount,
      success,
      error
    ) {
      return invoke("selectContacts", {
        enableMultiSelect,
        selectedUids,
        maxCount,
        success: Callback.add(success),
        error: Callback.add(error)
      });
    },

    /**
    * 绑定支付宝
    * PAY_REDPACKAGE("payRedpackage"),//调起支付宝客户端去支付
       AUTH_AliPAY("authAlipay"),//绑定支付宝

       RECORD_INIT("recordInit"),//录音权限初始化
       CAMERA_INIT("cameraInit"),//拍照权限初始化
       RED_PACKAGE_TAKE_CAMERA("redPackageTakeCamera"),//调起相机
       RED_PACKAGE_RECORD_START("redPackageSoundRecordStart"),//红包录音
       RED_PACKAGE_RECORD_END("redPackageSoundRecordEnd"),//红包录音结束
    */
    authAlipay: function(success) {
      return invoke("authAlipay", { success: Callback.add(success) });
    },
    /**
     * 红包支付
     * @param {*} payOrderStr
     * @param {*} success
     */
    payRedpackage: function(payOrderStr, success) {
      return invoke("payRedpackage", {
        payOrderStr: payOrderStr,
        success: Callback.add(success)
      });
    },

    /**
     * 拍照权限初始化
     * @param {*} success
     */
    cameraInit: function(success) {
      return invoke("cameraInit", { success: Callback.add(success) });
    },

    /**
     * 调起相机
     * @param {*} success
     */
    redPackageTakeCamera: function(success) {
      return invoke("redPackageTakeCamera", { success: Callback.add(success) });
    },

    /**
     * 红包录音开始
     * @param {*} recordType
     */
    redPackageSoundRecordStart: function(recordType) {
      return invoke("redPackageSoundRecordStart", { recordType: recordType });
    },

    /**
     * 红包录音结束
     * @param {*} success
     */
    redPackageSoundRecordEnd: function(success) {
      return invoke("redPackageSoundRecordEnd", {
        success: Callback.add(success)
      });
    },

    /**
     * 设置红包状态
     * @param {*} status
     * @param {*} messageID
     */
    setRedEnvelopeStatus: function(status, messageID) {
      return invoke("setRedEnvelopeStatus", {
        redEnvelopeStatus: status,
        messageID
      });
    },

    /**
     * @param params  Object
     * 红包发送结果
     */
    setRedEnvelopeSendResult: function(params) {
      return invoke("setRedEnvelopeSendResult", params);
    }
  };
})();
